package com.yenroc.invoice.service.impl;

import com.itextpdf.kernel.geom.PageSize;
import com.yenroc.invoice.pojo.*;
import com.yenroc.invoice.pojo.xml.FreightServiceXmlDTO;
import com.yenroc.invoice.pojo.xml.IssuItemInformationXmlDTO;
import com.yenroc.invoice.pojo.xml.SpecificInformationXmlDTO;
import com.yenroc.invoice.service.AbstractInvoice;
import com.yenroc.invoice.util.SerializationCloner;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
public class TransportInvoiceServiceImpl extends AbstractInvoice {
    /**
     * 数字化电子（货物运输服务）发票创建
     *
     * @param createDTO {@link TransportInvoiceCreateDTO TransportInvoiceCreateDTO}
     * @return JSONObject
     */
    public <T extends CommonInvoiceDTO> CreateInvoiceResult createInvoice(T createDTO) {
        return invokeInvoice(createDTO);
    }

    @Override
    protected Document getDocument() {
        try {
//            return Jsoup.parse(new File("src/main/resources/static/template/transportInvoice.html"), "utf-8");
//            return Jsoup.parse(new File(new ClassPathResource("/static/template/transportInvoice.html").getURI()), "utf-8");
            return Jsoup.parse(this.getClass().getResourceAsStream("/static/template/transportInvoice.html"),"utf-8", "");
        } catch (Exception e) {
            log.error("读取模板html error:", e);
        }
        return null;
    }

    @Override
    protected Document getFirstPageDocument() {
        try {
//            return Jsoup.parse(new File("src/main/resources/static/template/transportInvoiceFirstPage.html"), "utf-8");
//            return Jsoup.parse(new File(new ClassPathResource("/static/template/transportInvoiceFirstPage.html").getURI()), "utf-8");
            return Jsoup.parse(this.getClass().getResourceAsStream("/static/template/transportInvoiceFirstPage.html"),"utf-8", "");
        } catch (Exception e) {
            log.error("读取模板html error:", e);
        }
        return null;
    }

    @Override
    protected Document getMultiPageDocument() {
        try {
//            return Jsoup.parse(new File("src/main/resources/static/template/transportInvoiceMultiPage.html"), "utf-8");
//            return Jsoup.parse(new File(new ClassPathResource("/static/template/transportInvoiceMultiPage.html").getURI()), "utf-8");
            return Jsoup.parse(this.getClass().getResourceAsStream("/static/template/transportInvoiceMultiPage.html"),"utf-8", "");
        } catch (Exception e) {
            log.error("读取模板html error:", e);
        }
        return null;
    }

    @Override
    protected <T extends CommonInvoiceDTO> void fillInvoiceDetail(Document document, T dto) {
        Element goodsTbodyElement = document.getElementById("goodsTbody");
        if (goodsTbodyElement == null) {
            goodsTbodyElement = document.createElement("tbody");
            goodsTbodyElement.id("goodsTbody");
            goodsTbodyElement.addClass("goodsTbody");
        }
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        List<TransportInvoiceItemDetailDTO> itemDetails = transportInvoiceCreateDTO.getItemDetails();
        for (TransportInvoiceItemDetailDTO it : itemDetails) {
            Element goodsTrElement = document.createElement("tr");
            goodsTrElement.addClass("goodsTableTr");
            goodsTrElement.append(String.format("<td class=\"goodsTable1Col\">%s</td>", it.getGoodsName()));
            goodsTrElement.append(String.format("<td class=\"goodsTable2Col\">%s</td>", it.getGoodsSpecification() == null ? "" : it.getGoodsSpecification()));
            goodsTrElement.append(String.format("<td class=\"goodsTable3Col\">%s</td>", it.getGoodsUnit() == null ? "" : it.getGoodsUnit()));
            goodsTrElement.append(String.format("<td class=\"goodsTable4Col\">%s</td>", it.getGoodsQuantity() == null ? "" : it.getGoodsQuantity()));
            goodsTrElement.append(String.format("<td class=\"goodsTable5Col\">%s</td>", it.getGoodsPrice() == null ? "" : it.getGoodsPrice()));
            goodsTrElement.append(String.format("<td class=\"goodsTable6Col\">%s</td>", it.getGoodsTotalPrice()));
            goodsTrElement.append(String.format("<td class=\"goodsTable7Col\">%s</td>", formatTaxRate(it.getGoodsTaxRate(), it.getPreferentialPolicy())));
            goodsTrElement.append(String.format("<td class=\"goodsTable8Col\">%s</td>", formatGoodTax(it.getGoodsTaxRate(), it.getGoodsTax(), it.getPreferentialPolicy())));
            goodsTbodyElement.appendChild(goodsTrElement);
        }
        Element transportInfoTableBodyElement = document.getElementById("transportInfoTableBody");
        if (transportInfoTableBodyElement == null) {
            transportInfoTableBodyElement = document.createElement("tbody");
            transportInfoTableBodyElement.id("transportInfoTableBodyElement");
            transportInfoTableBodyElement.addClass("transportInfoTableBodyElement");
        }
        List<TransportInvoiceTypeDetailDTO> typeDetails = transportInvoiceCreateDTO.getTypeDetails();
        for (TransportInvoiceTypeDetailDTO it : typeDetails) {
            Element transportInfoTrElement = document.createElement("tr");
            transportInfoTrElement.addClass("transportInfoTableTr");
            transportInfoTrElement.append(String.format("<td class=\"transportType\">%s</td>", it.getTransportType() == null ? "" : it.getTransportType()));
            transportInfoTrElement.append(String.format("<td class=\"transportPlateNumber\">%s</td>", it.getTransportPlateNumber() == null ? "" : it.getTransportPlateNumber()));
            transportInfoTrElement.append(String.format("<td class=\"transportStartPlace\">%s</td>", it.getTransportStartPlace() == null ? "" : it.getTransportStartPlace()));
            transportInfoTrElement.append(String.format("<td class=\"transportEndPlace\">%s</td>", it.getTransportEndPlace() == null ? "" : it.getTransportEndPlace()));
            transportInfoTrElement.append(String.format("<td class=\"transportCargoName\">%s</td>", it.getTransportCargoName() == null ? "" : it.getTransportCargoName()));
            transportInfoTableBodyElement.appendChild(transportInfoTrElement);
        }
    }

    @Override
    public <T extends CommonInvoiceDTO> void fillInvoiceItemDetail(Document document, T dto) {
        Element goodsTbodyElement = document.getElementById("goodsTbody");
        if (goodsTbodyElement == null) {
            goodsTbodyElement = document.createElement("tbody");
            goodsTbodyElement.id("goodsTbody");
            goodsTbodyElement.addClass("goodsTbody");
        }
        Element invoiceBodyWrapperElement = document.getElementById("invoiceBodyWrapper");
        if (invoiceBodyWrapperElement != null) {
            TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
            int size = Math.abs(transportInvoiceCreateDTO.getTypeDetails().size()) * 31;
            int height = 80;
            System.out.println(size);
            if (size > 842) {
                height = 842;
            } else {
                height += size;
            }
            invoiceBodyWrapperElement.attr("style", "min-height: " + height + "px");
        }
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        List<TransportInvoiceItemDetailDTO> itemDetails = transportInvoiceCreateDTO.getItemDetails();
        for (TransportInvoiceItemDetailDTO it : itemDetails) {
            Element goodsTrElement = document.createElement("tr");
            goodsTrElement.addClass("goodsTableTr");
            goodsTrElement.append(String.format("<td class=\"goodsTable1Col\">%s</td>", it.getGoodsName()));
            goodsTrElement.append(String.format("<td class=\"goodsTable2Col\">%s</td>", it.getGoodsSpecification() == null ? "" : it.getGoodsSpecification()));
            goodsTrElement.append(String.format("<td class=\"goodsTable3Col\">%s</td>", it.getGoodsUnit() == null ? "" : it.getGoodsUnit()));
            goodsTrElement.append(String.format("<td class=\"goodsTable4Col\">%s</td>", it.getGoodsQuantity() == null ? "" : it.getGoodsQuantity()));
            goodsTrElement.append(String.format("<td class=\"goodsTable5Col\">%s</td>", it.getGoodsPrice() == null ? "" : it.getGoodsPrice()));
            goodsTrElement.append(String.format("<td class=\"goodsTable6Col\">%s</td>", it.getGoodsTotalPrice()));
            goodsTrElement.append(String.format("<td class=\"goodsTable7Col\">%s</td>", formatTaxRate(it.getGoodsTaxRate(), it.getPreferentialPolicy())));
            goodsTrElement.append(String.format("<td class=\"goodsTable8Col\">%s</td>", formatGoodTax(it.getGoodsTaxRate(), it.getGoodsTax(), it.getPreferentialPolicy())));
            goodsTbodyElement.appendChild(goodsTrElement);
        }
    }

    @Override
    public <T extends CommonInvoiceDTO> void fillInvoiceTypeDetail(Document document, T dto) {
        Element transportInfoTableBodyElement = document.getElementById("transportInfoTableBody");
        if (transportInfoTableBodyElement == null) {
            transportInfoTableBodyElement = document.createElement("tbody");
            transportInfoTableBodyElement.id("transportInfoTableBodyElement");
            transportInfoTableBodyElement.addClass("transportInfoTableBodyElement");
        }
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        List<TransportInvoiceTypeDetailDTO> typeDetails = transportInvoiceCreateDTO.getTypeDetails();
        for (TransportInvoiceTypeDetailDTO it : typeDetails) {
            Element transportInfoTrElement = document.createElement("tr");
            transportInfoTrElement.addClass("transportInfoTableTr");
            transportInfoTrElement.append(String.format("<td class=\"transportType\">%s</td>", it.getTransportType() == null ? "" : it.getTransportType()));
            transportInfoTrElement.append(String.format("<td class=\"transportPlateNumber\">%s</td>", it.getTransportPlateNumber() == null ? "" : it.getTransportPlateNumber()));
            transportInfoTrElement.append(String.format("<td class=\"transportStartPlace\">%s</td>", it.getTransportStartPlace() == null ? "" : it.getTransportStartPlace()));
            transportInfoTrElement.append(String.format("<td class=\"transportEndPlace\">%s</td>", it.getTransportEndPlace() == null ? "" : it.getTransportEndPlace()));
            transportInfoTrElement.append(String.format("<td class=\"transportCargoName\">%s</td>", it.getTransportCargoName() == null ? "" : it.getTransportCargoName()));
            transportInfoTableBodyElement.appendChild(transportInfoTrElement);
        }
    }

    @Override
    protected <T extends CommonInvoiceDTO> PageSize calculatePageSize(T dto) {
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        // 计算高度
        int lengthCount = transportInvoiceCreateDTO.getItemDetails().stream()
                .mapToInt(item -> Math.max(
                        item.getGoodsName().length() > 12 ? (int) Math.ceil((float) item.getGoodsName().length() / 12) : 1,
                        item.getGoodsPrice() != null && item.getGoodsPrice().toString().length() > 15 ? (int) Math.ceil((float) item.getGoodsPrice().toString().length() / 15) : 1)
                ).sum();
        int typeLineCount = transportInvoiceCreateDTO.getTypeDetails().stream()
                .mapToInt(item -> item.getTransportPlateNumber().length() > 24 ? (int) Math.ceil((float) item.getTransportPlateNumber().length() / 24) : 1)
                .sum();
//        if (lengthCount <= 7) {
//            return new PageSize(595f, 391f);
//        } else if (lengthCount == 8) {
//            return new PageSize(595f, 394f);
//        } else {
//            float i = calculateHeightIncrease(lengthCount);
//            float overHeight = (lengthCount - 8) * 11 + i;
//            return new PageSize(595f, 394f + overHeight);
//        }
        // TODO hyp 计算高度调整 仅考虑一页 运输服务（m = 1, n <= 10） （1mm ≈ 2.83）
        if (typeLineCount + lengthCount > 4) {
            float overHeight = (typeLineCount + lengthCount - 4) * 13.4F;
            return new PageSize(595f, 391f + overHeight);
        }
        return new PageSize(595f, 391f);
    }

    protected <T extends CommonInvoiceDTO> PageSize calculatePageSize2(T dto) {
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        // 计算高度
        int itemLineCount = transportInvoiceCreateDTO.getItemDetails().stream()
                .mapToInt(item -> Math.max(
                        item.getGoodsName().length() > 12 ? (int) Math.ceil((float) item.getGoodsName().length() / 12) : 1,
                        item.getGoodsPrice() != null && item.getGoodsPrice().toString().length() > 15 ? (int) Math.ceil((float) item.getGoodsPrice().toString().length() / 15) : 1)
                ).sum();
        int typeLineCount = transportInvoiceCreateDTO.getTypeDetails().stream()
                .mapToInt(item -> item.getTransportPlateNumber().length() > 24 ? (int) Math.ceil((float) item.getTransportPlateNumber().length() / 24) : 1)
                .sum();
        return calculateHeightCaseOne(itemLineCount, typeLineCount);
    }

    protected <T extends CommonInvoiceDTO> PageSize calculateHeightCaseOne(int m, int n) {
        float point = 0.352777778f;
//        float increase1 = 49.6f;
        float increase1 = 24f;
        float increase2 = 24.8f;
        float increase3 = 12.4f;
        float width = 595f;
        float height = 396f;
//        if (m <= 3) {
//            /*
//             * 当n≤4 行时, 发票高度140mm, 每条发票明细行款高度4.375mm；
//             * 当4<n≤8 行时, 发票高度增加17.5mm, 不换页；
//             * 当8<n≤12行时, 发票高度增加17.5mm, 不换页；
//             * 当12<n≤16行时, 发票高度增加17.5mm, 不换页；
//             * 当16<n≤20行时, 发票高度增加17.5mm, 不换页；
//             * 当20<n≤24行时, 发票高度增加17.5mm, 不换页；
//             * 当24<n≤28行时, 发票高度增加17.5mm, 不换页；
//             * 当28<n≤32行时, 发票高度增加17.5mm, 不换页；
//             * 当32<n≤36行时, 发票高度增加17.5mm, 不换页；
//             * 当36<n≤38行时, 发票高度增加8.75mm, 不换页；
//             * 当38<n≤43行时, 发票高度不变, 取最后一行明细信息换页处理。
//             * 换页后每页含有“票头”、“销售方和购买方信息”、“运输工具种类明细”和“票
//             * 尾”信息, 其中“价税合计（大写）”和“备注”模块只在末页展示。发票右上方（“发
//             * 票日期”内容填充区域下方）增加“共X 页 第X 页”。
//             */
//            if (n <= 4) {
//            }
//            if (4 < n && n <= 8) {
//                height += increase1;
//            }
//            if (8 < n && n <= 12) {
//                height += increase1;
//            }
//            if (12 < n && n <= 16) {
//                height += increase1;
//            }
//            if (16 < n && n <= 20) {
//                height += increase1;
//            }
//            if (20 < n && n <= 24) {
//                height += increase1;
//            }
//            if (24 < n && n <= 28) {
//                height += increase1;
//            }
//            if (28 < n && n <= 32) {
//                height += increase1;
//            }
//            if (32 < n && n <= 36) {
//                height += increase1;
//            }
//            if (36 < n && n <= 38) {
//                height += increase2;
//            }
//            if (38 < n && n <= 43) {
//                // 发票高度不变, 取最后一行明细信息换页处理
//            }
//        }
//        if (m > 3 && n <= 4) {
//            /*
//             * 当m≤3 行时, 发票高度140mm, 每条发票明细行款高度4.375mm；
//             * 当3<m≤7 行时, 发票高度增加17.5mm, 不换页；
//             * 当7<m≤11行时, 发票高度增加17.5mm, 不换页；
//             * 当11<m≤15行时, 发票高度增加17.5mm, 不换页；
//             * 当15<m≤19 行时, 发票高度增加17.5mm, 不换页；
//             * 当19<m≤23 行时, 发票高度增加17.5mm, 不换页；
//             * 当23<m≤27 行时, 发票高度增加17.5mm, 不换页；
//             * 当27<m≤31 行时, 发票高度增加17.5mm, 不换页；
//             * 当31<m≤35 行时, 发票高度增加17.5mm, 不换页；
//             * 当35<m≤37 行时, 发票高度增加8.75mm, 不换页；
//             * 当37<m≤47 行时, 发票高度不变, 取运输工具种类明细信息换页处理。
//             * 换页后每页含有“票头”、“销售方和购买方信息”、“应税明细信息”和“票尾”
//             * 信息, 其中“价税合计（大写）”和“备注”模块只在末页展示。发票右上方（“发票
//             * 日期”内容填充区域下方）增加“共X 页 第X 页”。
//             * 当47<m 行时, 每页项目明细“合计”上方增加一行“小计”。
//             */
//            if (m <= 3) {
//
//            }
//            if (3 < m && m <= 7) {
//                height += increase1;
//            }
//            if (7 < m && m <= 11) {
//                height += increase1;
//            }
//            if (11 < m && m <= 15) {
//                height += increase1;
//            }
//            if (15 < m && m <= 19) {
//                height += increase1;
//            }
//            if (19 < m && m <= 23) {
//                height += increase1;
//            }
//            if (23 < m && m <= 27) {
//                height += increase1;
//            }
//            if (27 < m && m <= 31) {
//                height += increase1;
//            }
//            if (31 < m && m <= 35) {
//                height += increase1;
//            }
//            if (35 < m && m <= 37) {
//                height += increase2;
//            }
//            if (37 < m && m <= 47) {
//                // 发票高度不变, 取运输工具种类明细信息换页处理
//            }
//        }
//        if (m > 3 && n > 4) {
//            /*
//             * 发票高度每次增加行高度（即17.5mm）, m+n最多41 行,且m<33不换页；
//             * 当33<m<47,发票高度不变, 取运输工具种类明细信息换页处理。
//             * 当47<m 行时, 含有项目明细页“合计”上方增加一行“小计”。
//             * 换页后每页含有“票头”、“销售方和购买方信息”、“应税明细信息”和“票尾”
//             * 信息, 其中“价税合计（大写）”和“备注”模块只在末页展示。发票右上方（“发票
//             * 日期”内容填充区域下方）增加“共X 页 第X 页”。
//             */
//            if (33 < m && m < 47) {
//                // 发票高度不变, 取运输工具种类明细信息换页处理
//            }
//            if (47 < m) {
//                // 含有项目明细页“合计”上方增加一行“小计”。
//            }
//        }
        if (m + n < 41) {
            height = (m + n) / 4f * increase1 + height;
        } else {
            height = 41 * increase1 / 4f + height;
        }
        log.info("new PageSize({}, {})", width, height);
        if (height > 842) {
            height = 842;
        } else {
            height += 296;
        }
//        return new PageSize(width, height);
        return new PageSize(PageSize.A4);
    }

    protected <T extends CommonInvoiceDTO> int calculatePageable(T dto) {
        int page = 1;
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        int itemLineCount = transportInvoiceCreateDTO.getItemDetails().stream()
                .mapToInt(item -> item.getGoodsName().length() > 12 ? (int) Math.ceil((float) item.getGoodsName().length() / 12) : 1)
                .sum();
        int typeLineCount = transportInvoiceCreateDTO.getTypeDetails().stream()
                .mapToInt(item -> item.getTransportPlateNumber().length() > 24 ? (int) Math.ceil((float) item.getTransportPlateNumber().length() / 24) : 1)
                .sum();
        if (21 < itemLineCount + typeLineCount) {
            page = 2;
        }
        if (41 < itemLineCount + typeLineCount) {
            page = 3;
        }
        return page;
    }

    protected <T extends CommonInvoiceDTO> int calculateItemDetailCount(T dto) {
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        return transportInvoiceCreateDTO.getItemDetails().stream()
                .mapToInt(item -> item.getGoodsName().length() > 12 ? (int) Math.ceil((float) item.getGoodsName().length() / 12) : 1)
                .sum();
    }

    protected <T extends CommonInvoiceDTO> int calculateTypeDetailCount(T dto) {
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        return transportInvoiceCreateDTO.getTypeDetails().stream()
                .mapToInt(item -> item.getTransportPlateNumber().length() > 24 ? (int) Math.ceil((float) item.getTransportPlateNumber().length() / 24) : 1)
                .sum();
    }

    @Override
    protected <T extends CommonInvoiceDTO> List<String> getHtmlStrList(String qrCode, String invoiceStamp, T dto) {
        int typeDetailCount = calculateTypeDetailCount(dto);
        TransportInvoiceCreateDTO transportInvoiceCreateDTO = (TransportInvoiceCreateDTO) dto;
        List<String> list = new ArrayList<>();
        List<TransportInvoiceItemDetailDTO> itemDetails = transportInvoiceCreateDTO.getItemDetails();
        List<TransportInvoiceTypeDetailDTO> typeDetails = transportInvoiceCreateDTO.getTypeDetails();
        if (typeDetailCount <= 22) {
            String htmlStr = getInvoiceHtml(qrCode, invoiceStamp, null, dto);
            list.add(htmlStr);
        } else if (23 < typeDetailCount && typeDetailCount < 49) {
            List<TransportInvoiceTypeDetailDTO> firstList = new ArrayList<>();
            List<TransportInvoiceTypeDetailDTO> secondList = new ArrayList<>();
            // 遍历子列表并生成html字符串, 添加到新的list中
            for (int i = 0; i < typeDetails.size(); i++) {
                if (i < 11) {
                    firstList.add(typeDetails.get(i));
                } else {
                    secondList.add(typeDetails.get(i));
                }
            }
            TransportInvoiceCreateDTO dto1 = SerializationCloner.deepCopy(transportInvoiceCreateDTO);
            dto1.setTypeDetails(secondList);
            transportInvoiceCreateDTO.setTypeDetails(firstList);
            String htmlStr = getFirstPageDocument(qrCode, invoiceStamp, new InvoicePageInfo(2, 1), transportInvoiceCreateDTO);
            list.add(htmlStr);
            String htmlStr2 = getMultiPageInvoiceHtml(qrCode, invoiceStamp, new InvoicePageInfo(2, 2), dto1);
            list.add(htmlStr2);
        } else {
            List<TransportInvoiceTypeDetailDTO> firstList = new ArrayList<>();
            List<TransportInvoiceTypeDetailDTO> secondList = new ArrayList<>();
            List<TransportInvoiceTypeDetailDTO> thirdList = new ArrayList<>();
            // 遍历子列表并生成html字符串, 添加到新的list中
            for (int i = 0; i < typeDetails.size(); i++) {
                if (i < 11) {
                    firstList.add(typeDetails.get(i));
                } else if (11 < i && i < 32) {
                    secondList.add(typeDetails.get(i));
                } else {
                    thirdList.add(typeDetails.get(i));
                }
            }
            TransportInvoiceCreateDTO dto2 = SerializationCloner.deepCopy(transportInvoiceCreateDTO);
            TransportInvoiceCreateDTO dto3 = SerializationCloner.deepCopy(transportInvoiceCreateDTO);

            dto2.setTypeDetails(secondList);
            dto3.setTypeDetails(thirdList);
            transportInvoiceCreateDTO.setTypeDetails(firstList);
            String htmlStr = getFirstPageDocument(qrCode, invoiceStamp, null, transportInvoiceCreateDTO);
            list.add(htmlStr);
            String htmlStr2 = getMultiPageInvoiceHtml(qrCode, invoiceStamp, null, dto2);
            list.add(htmlStr2);
            String htmlStr3 = getMultiPageInvoiceHtml(qrCode, invoiceStamp, null, dto3);
            list.add(htmlStr3);

        }
        return list;
    }

    @Override
    protected <T extends CommonInvoiceDTO> SpecificInformationXmlDTO getSpecificInformation(T dto) {
        List<FreightServiceXmlDTO> list = new ArrayList<>();
        TransportInvoiceCreateDTO createDTO = (TransportInvoiceCreateDTO) dto;
        for (TransportInvoiceTypeDetailDTO typeDetail : createDTO.getTypeDetails()) {
            list.add(FreightServiceXmlDTO.builder()
                    .departure(typeDetail.getTransportStartPlace())
                    .destination(typeDetail.getTransportEndPlace())
                    .typeOfTransportationMeans(typeDetail.getTransportType())
                    .transportationMeansNo(typeDetail.getTransportPlateNumber())
                    .nameOfGoodsTransported(typeDetail.getTransportCargoName())
                    .build());
        }
        return SpecificInformationXmlDTO.builder()
                .freightService(list)
                .build();
    }

    @Override
    protected <T extends CommonInvoiceDTO> List<IssuItemInformationXmlDTO> getIssuItemInformation(T dto) {
        List<IssuItemInformationXmlDTO> list = new ArrayList<>();
        TransportInvoiceCreateDTO createDTO = (TransportInvoiceCreateDTO) dto;
        List<TransportInvoiceItemDetailDTO> detailList = createDTO.getItemDetails();
        if (detailList != null && detailList.size() > 0) {
            for (TransportInvoiceItemDetailDTO detail : detailList) {
                list.add(IssuItemInformationXmlDTO.builder()
                        .itemName(detail.getGoodsName())
                        .specMod(detail.getGoodsSpecification())
                        .meaUnits(detail.getGoodsUnit())
                        .quantity(detail.getGoodsQuantity())
                        .unPrice(detail.getGoodsPrice())
                        .amount(detail.getGoodsTotalPrice())
                        .taxRate(detail.getGoodsTaxRate())
                        .comTaxAm(detail.getGoodsTax())
                        .totaltaxIncludedAmount(Objects.nonNull(detail.getTotalTaxIncludedAmount()) ? detail.getTotalTaxIncludedAmount() : detail.getGoodsTotalPrice().add(detail.getGoodsTax()))
                        .taxClassificationCode(detail.getTaxClassificationCode())
                        .build());
            }
        }
        return list;
    }

}